
import useService from "@/hooks/useService";

import { lowcodeDebounceAsync } from "../utils";
import { LowcodeDataLinkOptions } from "../interface";
import type { DataEventHookProxy, DataEventProxy, FetchScriptProxy, FetchScriptReq, FetchScriptRes } from "./interface";
import { LOWCODERUNTIMEUNIQUEKEY, lowcodeDebounceTime } from "../constant";

const useLowcodeDataEvent = (hookProxy?: DataEventHookProxy) => {
  // const { itemsConfig } = hookProxy || {};
  const mainService = useService({ prefix: "mainApi" });

  const logicFunc = ({ sVal, logic, tVal }) => {
    let logicRes = true;
    switch (logic) {
      case "等于":
        {
          logicRes = (sVal === 0 ? "0" : ((sVal || "") + "")) === tVal
        }
        break;
      case "相似":
      case "包含":
        {
          logicRes = sVal?.includes?.(tVal);
        }
        break;
      case "不相似":
      case "不包含":
        {
          logicRes = !sVal?.includes?.(tVal);
        }
        break;
      case "左相似":
        {
          logicRes = sVal?.startsWith?.(tVal);
        }
        break;
      case "为空":
        {
          logicRes = !sVal && sVal !== 0;
        }
        break;
      case "不为空":
        {
          logicRes = !!sVal || sVal === 0;
        }
        break;
      default:
        break;
    }

    return logicRes;
  };

  const fetchScript = async (proxy: FetchScriptProxy) => {
    const { title, record, sqlRule } = proxy;

    const { service, sql, msg, conditions, fieldMap } = sqlRule;
    const fieldMapConf = Array.isArray(fieldMap) ? fieldMap?.reduce((obj, f) => (f.targetField ? { ...obj, [f.targetField]: f.sourceField } : obj), {}) : null;

    if (!sql || !fieldMapConf || !Object.keys(fieldMapConf)?.length || !Array.isArray(conditions) || !conditions?.length) {
      return null;
    }

    const conditionValidated = conditions?.some(orItem => {
      const andItems = orItem?.ruleItems;
      const orLogicRes = andItems?.every(andItem => {
        const { fieldId, logic, value } = andItem || {};
        const andItemLogicRes = logicFunc({ sVal: record[fieldId || ""], logic, tVal: value });
        return andItemLogicRes;
      });
      return orLogicRes;
    });
    if (!conditionValidated) {
      return null;
    }

    let mergeRowData: { [key: string]: any } = {}; // TODO DataEventItems 现在的字典key(dictKey)是临时取得，后面调整了再改
    const fetchReqProxy = { ModuleCode: hookProxy?.mdCode || "" };
    const fetchReq = { RowData: record, DataEventItems: { dictKey: { Title: title, ServiceName: service, FetchSql: sql } } };
    const fetchRes = await mainService.request<FetchScriptReq, FetchScriptRes>(LOWCODERUNTIMEUNIQUEKEY, "DataEvent", fetchReq, "", "", fetchReqProxy);

    // console.log("fetchScript fetchRes ", fetchRes);
    if (fetchRes?.DataEventItems) {
      const fetchResData = Object.values(fetchRes?.DataEventItems);
      const dataItems = fetchResData?.[0]?.DataItems;
      const firstData = dataItems?.[0];

      if (firstData) {
        Object.keys(fieldMapConf)?.forEach(fieldKey => mergeRowData[fieldKey] = firstData[fieldMapConf[fieldKey]]);
      }
      
      // 现在还确定移动端的错误提示方式
      let modalCnt = "";
      if (fetchResData?.[0]?.ErrorMsg) {
        modalCnt = fetchResData[0].ErrorMsg;
      } else if ((!Array.isArray(dataItems) || !dataItems?.length) && msg) {
        modalCnt = msg;
      }

		  modalCnt && uni.showModal({ title: "提示", content: modalCnt, showCancel: false, success: (res) => {} });
    }

    return mergeRowData;
  };

  const handleEventDataDebounce = async (proxy: DataEventProxy) => {
    const { itemsConfig, record, fieldName, newValue } = proxy;
    // console.log("useLowcodeDataEvent ", itemsConfig);

    const datalinkConfigItems: { [key: string]: any } = Array.isArray(itemsConfig) ? itemsConfig?.reduce((obj, item) => {
      const linkItemCFG = item?.c_datalink?.linkItemCFG;
      return (Array.isArray(linkItemCFG) && linkItemCFG?.length) ? { ...obj, [(item?.c_code || "")]: linkItemCFG } : obj;
    }, {}) : {};

    const recordValidated = typeof record !== "object";
    const proxyConfig = itemsConfig;
    const datalinkConfig = datalinkConfigItems;
    // console.log("useLowCodeDataEvent handleEventData === ", record, fieldName, newValue, itemsConfig);

    if (!Array.isArray(proxyConfig) || !proxyConfig?.length || recordValidated || !datalinkConfig) {
      return null;
    }
    if (!Object.keys(datalinkConfig)?.length || !datalinkConfig?.[fieldName]) {
      return null;
    }
    // console.log("handleEventData datalinkConfig === ", datalinkConfig);

    let newRecord: { [key: string]: any } = {};
    const fieldLinkItems = datalinkConfig[fieldName];

    uni.showLoading({ title: "正在处理数据，请稍等......", mask: true });
    for (let i = 0; i < fieldLinkItems.length; i++) {
      const ruleI = fieldLinkItems[i], mergeRecord: { [key: string]: any } = { ...record, ...newRecord };
      const { title, linkType, sqlRule, conditionRule } = ruleI || {};

      if (linkType === LowcodeDataLinkOptions.取数脚本) {
        const fetchRes = await fetchScript({ title, record: mergeRecord, sqlRule });
        fetchRes && (newRecord = { ...newRecord, ...fetchRes });
        continue;
      }

      if (!Array.isArray(conditionRule) || !conditionRule?.length) {
        continue;
      }

      conditionRule?.forEach(targetFieldConfig => {
        const { targetField, value, groups } = targetFieldConfig || {};

        if (!targetField || !Array.isArray(groups) || !groups.length) {
          return;
        }

        const conditionValidated = groups?.some(orItem => {
          const andItems = orItem?.ruleItems;
          const orLogicRes = andItems?.every(andItem => {
            const { fieldId, logic, value } = andItem || {};
            const andItemLogicRes = logicFunc({ sVal: mergeRecord[fieldId], logic, tVal: value });
            return andItemLogicRes;
          });
          return orLogicRes;
        });

        conditionValidated && (newRecord = { ...newRecord, [targetField]: value });

      }); // forEach end
    }
    uni.hideLoading();
    return newRecord;
  };

  const handleEventData = lowcodeDebounceAsync(handleEventDataDebounce, lowcodeDebounceTime);
  return { handleEventData };
}

export default useLowcodeDataEvent;
